package cgs_worksheet

import (
	"cgs-server/helper"
	"cgs-server/pkg/set"
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/model"
	"cgs-server/server/system"
	"errors"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
	"strings"
	"time"
)

type WorksheetService interface {
	Export(visualId string, formIdSet set.Set, user *system.User) ([]*model.ZipFileData, error)
	// Import 导入表单数据，
	// zipData 解压后的数据，
	// categoryId 分类id，
	// visualId 视图id，
	// user 当前用户
	Import(zipData []*model.ZipFileData, visualType, categoryId string, visualId string, user *model.User) (*bson.M, error)
	base.Service
	UpdateFields(mdl *model.DataUserModel) error

	// 添加表单数据
	AddRow(mdl *model.DataUserModel) error
	// 批量添加表单数据
	BatchAddRow(mdl *model.DataUserModel) error
	// 更新表单数据
	UpdateRow(mdl *model.DataUserModel) error
	// 批量更新表单数据
	UpdateRowBatch(mdl *model.DataUserModel) error
	// 删除数据
	DeleteRowLogic(mdl *model.DataUserModel) error
	// 批量删除数据
	BatchDeleteRow(mdl *model.DataUserModel) error
	// 导入表格数据
	ImportExcelData(mdl *model.DataUserModel) error

	// 获取某个应用下的表格信息
	ListAppWorksheet(mdl *model.DataUserModel) (interface{}, error)
	// GetFilterRows 获取记录列表
	GetFilterRows(mdl *model.DataUserModel) (interface{}, error)

	// 获取行记录详情
	GetRowById(mdl *model.DataUserModel) (interface{}, error)

	// 获取最大最小值
	GetMaxMinValue(mdl *model.DataUserModel) (interface{}, error)

	// ClearWorksheet 清空表单数据
	ClearWorksheet(worksheetId primitive.ObjectID, user *model.User) error

	// Export2Excel 导出表单数据到Excel
	Export2Excel(param FilterParam) (*excelize.File, string, error)
}

func NewWorksheetService() WorksheetService {
	return &worksheetService{
		worksheetRepo: NewWorksheetRepository(),
	}
}

type worksheetService struct {
	worksheetRepo WorksheetRepository
	base.ServiceImpl
}

func (w *worksheetService) Export2Excel(param FilterParam) (*excelize.File, string, error) {
	name := ""
	one, err := w.worksheetRepo.FindOne(&model.DataUserModel{
		Data: &WorksheetInfo{
			Id: param.WorksheetId,
		},
	})
	if err != nil {
		return nil, name, err
	}
	wk := one.(*WorksheetInfo)
	name = wk.WsName
	param.WsCollection = wk.WsCollection

	filter := param.GetFilterParam(wk).Map()
	formData, err := w.worksheetRepo.FindFilterFormData(&model.DataUserModel{
		Data:   &param,
		Filter: &filter,
	})
	if err != nil {
		return nil, name, err
	}

	data := formData.(bson.A)
	docs := FormatDataType(data, *wk)

	// 写入到 excel
	var (
		axis    = ""
		colName = ""
		sheet   = "Sheet1"
	)
	f := excelize.NewFile()

	titleStyle, err := f.NewStyle(`{
    "font":
    {
        "bold": true
    }
}`)
	if err != nil {
		return nil, name, err
	}

	// 设置标题
	for i, field := range wk.Fields {
		index := i + 1
		colName, err = excelize.ColumnNumberToName(index)
		if err != nil {
			return nil, name, err
		}
		axis, err = excelize.JoinCellName(colName, 1)
		if err != nil {
			return nil, name, err
		}
		err = f.SetCellValue(sheet, axis, field.Alia)
		if err != nil {
			return nil, name, err
		}
		err = f.SetCellStyle(sheet, axis, axis, titleStyle)
		if err != nil {
			return nil, "", err
		}
	}

	// 设置数据
	for i, d := range docs {
		rowData := d.(bson.M)
		for fi, field := range wk.Fields {
			if v, ok := rowData[field.Name]; ok {
				colName, err = excelize.ColumnNumberToName(fi + 1)
				if err != nil {
					return nil, name, err
				}
				axis, err = excelize.JoinCellName(colName, i+2)
				if err != nil {
					return nil, name, err
				}
				err = f.SetCellValue(sheet, axis, v)
				if err != nil {
					return nil, name, err
				}
			}
		}
	}

	return f, name, nil
}

func (w *worksheetService) ClearWorksheet(worksheetId primitive.ObjectID, user *model.User) error {
	wsInfo := &WorksheetInfo{
		Id: worksheetId,
	}
	result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
		Data: wsInfo,
		User: user,
	})
	if err != nil {
		return err
	}
	if result == nil {
		return errors.New("worksheet is no found")
	}
	wsInfoRes := result.(*WorksheetInfo)

	// 权限校验
	if len(wsInfoRes.VisualData) == 2 && !user.HasVisualAuth(wsInfoRes.VisualData[1]) {
		return errors.New("Permission denied.")
	}
	if len(wsInfoRes.VisualData) == 3 && !user.HasVisualAuth(wsInfoRes.VisualData[2]) {
		return errors.New("Permission denied.")
	}

	return w.worksheetRepo.ClearData(wsInfoRes.WsCollection)
}

func (w *worksheetService) ListAppWorksheet(mdl *model.DataUserModel) (interface{}, error) {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		// 判断用户是否有此应用的权限
		if !mdl.User.HasVisualAuth(wsInfo.VisualId) {
			return nil, errors.New("Permission denied.")
		}

		filter := bson.M{
			"visualData": wsInfo.VisualId,
		}
		mdl.Filter = &filter
		mdl.Options = &options.FindOptions{
			Projection: bson.M{
				"fields":       0,
				"tenantId":     0,
				"wsCollection": 0,
				"config":       0,
			},
		}
		result, err := w.worksheetRepo.Find(mdl)
		if err != nil {
			return nil, err
		}
		/*count, err := w.worksheetRepo.Count(mdl)
		if err != nil {
			return nil, err
		}
		if mdl.Page == nil {
			mdl.Page = &model.Page{
				Current: 0,
				Size:    0,
			}
		}
		res := server.PageResult{
			CgsResult: server.CgsResult{
				Code: 200,
				Msg:  "Get Successfully!",
				Data: result,
			},
			PageNo: mdl.Page.Current,
			PageSize: mdl.Page.Size,
			TotalCount: count,
		}
		res.CalculateTotalPage()*/
		return result, nil
	} else {
		return nil, errors.New("WorksheetInfo type error")
	}
}

func (w *worksheetService) ImportExcelData(mdl *model.DataUserModel) error {
	if importExcelVo, ok := mdl.Data.(*ImportExcelVo); ok {
		// 1. 查询表单信息
		if importExcelVo.WorksheetId.IsZero() {
			return errors.New("worksheetIs is empty")
		}
		wsInfo := &WorksheetInfo{
			Id: importExcelVo.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)
		// 2. 导入数据
		importExcelVo.WsInfo = wsInfoRes
		err = importExcelVo.DealWorksheetData()
		if err != nil {
			return err
		}

		// 检查记录数
		err = w.checkLicense(importExcelVo.WsInfo.WsCollection, len(importExcelVo.RowList))
		if err != nil {
			return err
		}

		err = w.worksheetRepo.ImportExcelData(mdl)
		return err
	} else {
		return errors.New("BatchDeleteRowVo type error")
	}
}

func (w *worksheetService) BatchDeleteRow(mdl *model.DataUserModel) error {
	if batchDeleteRowVo, ok := mdl.Data.(*BatchDeleteRowVo); ok {
		// 1. 查询表单信息
		if batchDeleteRowVo.WorksheetId.IsZero() {
			return errors.New("worksheetIs is empty")
		}
		wsInfo := &WorksheetInfo{
			Id: batchDeleteRowVo.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 向前端推一下数据
		ids := bson.A{}
		for _, id := range batchDeleteRowVo.RowIds {
			bsonId, err := primitive.ObjectIDFromHex(id)
			if err == nil {
				ids = append(ids, bsonId)
			}
			ids = append(ids, id)
		}
		filter := bson.M{
			"rowId": bson.M{
				"$in": ids,
			},
		}

		if batchDeleteRowVo.IsAll {
			filter = bson.M{}
		}

		data, _ := w.worksheetRepo.FindFilterFormData(&model.DataUserModel{
			Data: &FilterParam{
				WsCollection: wsInfoRes.WsCollection,
			},
			User:   mdl.User,
			Filter: &filter,
		})

		// 2. 更新数据
		batchDeleteRowVo.WsInfo = wsInfoRes
		err = w.worksheetRepo.BatchDeleteFormDataLogic(mdl)

		if err == nil {
			server.WebsocketHub.Send(&server.BroadcastMessage{Type: WsDeleteRow, Data: data})
		}
		return err
	} else {
		return errors.New("BatchDeleteRowVo type error")
	}
}

func (w *worksheetService) DeleteRowLogic(mdl *model.DataUserModel) error {
	if wsRowData, ok := mdl.Data.(*WsRowData); ok {
		// 1. 查询表单信息
		/*worksheetId, err := primitive.ObjectIDFromHex(wsRowData.WorksheetId)
		if err != nil {
			return err
		}*/
		wsInfo := &WorksheetInfo{
			Id: wsRowData.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 权限校验
		if len(wsInfoRes.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[1]) {
			return errors.New("Permission denied.")
		}
		if len(wsInfoRes.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[2]) {
			return errors.New("Permission denied.")
		}

		// 向前端推一下数据
		rowById, _ := w.GetRowById(mdl)

		// 2. 更新数据
		wsRowData.WsInfo = wsInfoRes
		err = w.worksheetRepo.DeleteOneFormDataLogic(mdl)

		if err == nil {
			server.WebsocketHub.Send(&server.BroadcastMessage{Type: WsDeleteRow, Data: rowById})
		}

		return err
	} else {
		return errors.New("WsRowData type error")
	}
}

func (w *worksheetService) UpdateRow(mdl *model.DataUserModel) error {
	if wsRowData, ok := mdl.Data.(*WsRowData); ok {
		// 1. 查询表单信息
		/*worksheetId, err := primitive.ObjectIDFromHex(wsRowData.WorksheetId)
		if err != nil {
			return err
		}*/
		wsInfo := &WorksheetInfo{
			Id: wsRowData.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 权限校验
		if len(wsInfoRes.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[1]) {
			return errors.New("Permission denied.")
		}
		if len(wsInfoRes.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[2]) {
			return errors.New("Permission denied.")
		}

		// 2. 更新数据
		wsRowData.WsInfo = wsInfoRes
		err = wsRowData.TransferData()
		if err != nil {
			return err
		}
		err = w.worksheetRepo.UpdateOneFormData(mdl)

		// 向前端推一下数据
		if err == nil {
			rowById, err := w.GetRowById(mdl)
			if err == nil {
				server.WebsocketHub.Send(&server.BroadcastMessage{Type: WsUpdateRow, Data: rowById})
			}
		}

		return err
	} else {
		return errors.New("WsRowData type error")
	}
}

func (w *worksheetService) UpdateRowBatch(mdl *model.DataUserModel) error {
	if wsRowDataBatch, ok := mdl.Data.(*WsRowDataBatch); ok {
		// 1. 查询表单信息
		wsInfo := &WorksheetInfo{
			Id: wsRowDataBatch.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 权限校验
		if len(wsInfoRes.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[1]) {
			return errors.New("Permission denied.")
		}
		if len(wsInfoRes.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[2]) {
			return errors.New("Permission denied.")
		}

		// 2. 更新数据
		if wsRowDataBatch.IsAll {
			filterParam := wsRowDataBatch.GetFilterParam(wsInfoRes).Map()
			mdl.Filter = &filterParam
		}
		wsRowDataBatch.WsInfo = wsInfoRes
		err = wsRowDataBatch.TransferData()
		if err != nil {
			return err
		}
		err = w.worksheetRepo.UpdateFormDataBatch(mdl)

		// 向前端推一下数据
		if err == nil {
			ids := bson.A{}
			for _, id := range wsRowDataBatch.RowIds {
				bsonId, err := primitive.ObjectIDFromHex(id)
				if err == nil {
					ids = append(ids, bsonId)
				}
				ids = append(ids, id)
			}
			filter := bson.M{
				"rowId": bson.M{
					"$in": ids,
				},
			}

			data, _ := w.worksheetRepo.FindFilterFormData(&model.DataUserModel{
				Data: &FilterParam{
					WsCollection: wsInfoRes.WsCollection,
				},
				User:   mdl.User,
				Filter: &filter,
			})
			server.WebsocketHub.Send(&server.BroadcastMessage{Type: WsUpdateRow, Data: data})
		}

		return err
	} else {
		return errors.New("WsRowData type error")
	}
}

// 根据条件查询表单数据，无分页
func (w *worksheetService) GetMaxMinValue(mdl *model.DataUserModel) (interface{}, error) {
	if filterParam, ok := mdl.Data.(*FilterParam); ok {
		// 查询表单信息
		wsRes, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: &WorksheetInfo{
				Id: filterParam.WorksheetId,
			},
		})
		if err != nil {
			return nil, err
		}
		if wsRes == nil {
			return nil, model.NotFoundError("worksheet id " + filterParam.WorksheetId.Hex())
		}
		wsInfo := wsRes.(*WorksheetInfo)

		filterParam.WsCollection = wsInfo.WsCollection

		projection := bson.M{
			"_id":       0,
			"isDeleted": 0,
		}

		opts := options.FindOptions{
			Projection: projection,
			Sort: bson.M{
				filterParam.SortField: 1,
			},
		}
		mdl.Options = &opts
		filter := filterParam.GetFilterParam(wsInfo).Map()
		mdl.Filter = &filter

		data, err := w.worksheetRepo.FindFilterFormData(mdl)
		if err != nil {
			return nil, err
		}
		doc := data.(bson.A)
		docs := FormatDataType(doc, *wsInfo)

		return docs, nil
	} else {
		return nil, model.NewTypeError("filterParam")
	}
}

/*func (w *worksheetService) Init() error {
	return w.worksheetRepo.InitDB()
}*/

func (w *worksheetService) Export(visualId string, formIdSet set.Set, user *system.User) ([]*model.ZipFileData, error) {
	if visualId == "" {
		return nil, errors.New("VisualId is required.")
	}
	if user == nil {
		return nil, errors.New("Permission denied.")
	}
	wss, err := w.worksheetRepo.FindByVisualId(visualId, user)
	if err != nil {
		return nil, err
	}

	// 去重
	for _, info := range wss {
		formIdSet.Add(info.GetId())
	}
	stringIds := formIdSet.ToSlice()
	ids := make([]primitive.ObjectID, 0, formIdSet.Size())
	for i := range stringIds {
		bsonId, err := primitive.ObjectIDFromHex(stringIds[i].(string))
		if err != nil {
			continue
		}
		ids = append(ids, bsonId)
	}

	// 查询表单数据
	worksheets, err := w.worksheetRepo.FindByFormIds(ids)
	if err != nil {
		return nil, err
	}

	var zipData []*model.ZipFileData
	res, err := helper.ToJSON(worksheets)
	if err != nil {
		return nil, err
	}
	if len(res) == 0 {
		return zipData, nil
	}
	zipData = append(zipData, &model.ZipFileData{
		Name: server.ExportFormFile + "form.json",
		Body: res,
	})

	// 导出表单数据
	for _, ws := range worksheets {
		formData, err := w.worksheetRepo.FindFormData(ws.WsCollection)
		if err != nil {
			return nil, err
		}
		docs := FormatDataType(*formData, *ws)
		docRes, err := helper.ToJSON(docs)
		if err != nil {
			return nil, err
		}
		zipData = append(zipData, &model.ZipFileData{
			Name: server.ExportFormFile + "formData/" + ws.Id.Hex() + ".json",
			Body: docRes,
		})
	}

	return zipData, nil
}

func (w *worksheetService) Import(zipData []*model.ZipFileData, visualType, categoryId string, visualId string, user *model.User) (*bson.M, error) {
	//if err := w.Init(); err != nil {
	//	return nil, err
	//}

	idData := bson.M{}
	for idx := range zipData {
		if strings.HasSuffix(zipData[idx].Name, "form.json") {
			wsInfos := []*WorksheetInfo{}
			err := helper.FromJSON(zipData[idx].Body, &wsInfos)
			if err != nil {
				return nil, err
			}
			for _, wsInfo := range wsInfos {
				oldWsId := wsInfo.Id
				wsInfo.Id = primitive.NewObjectID()
				//wsInfo.WsName += "_copy"
				wsInfo.WsCollection = "ws" + wsInfo.Id.Hex()
				wsInfo.UpdateTime = time.Now()
				wsInfo.CreateTime = time.Now()

				for _, field := range wsInfo.Fields {
					field.DataType = int32(field.DataType.(float64))
				}

				wsInfo.VisualData = []string{visualType, categoryId, visualId}
				// 权限
				wsInfo.UserId = user.UserId.Hex()
				isDeleted := 0
				wsInfo.IsDeleted = &isDeleted
				wsInfo.TenantId = user.TenantId

				// 添加到数据库
				err = w.worksheetRepo.Insert(&model.DataUserModel{
					Data: wsInfo,
					User: user,
				})
				if err != nil {
					return nil, err
				}

				idData[oldWsId.Hex()] = wsInfo.Id.Hex()

				// 查找表单数据，并导入
				for idx, _ := range zipData {
					if strings.Contains(zipData[idx].Name, oldWsId.Hex()) {
						docArr := bson.A{}
						if err = helper.FromJSON(zipData[idx].Body, &docArr); err != nil {
							return nil, err
						}
						if len(docArr) > 0 {
							fmt.Println("开始导入表单数据>>>>>")
							// todo 添加到数据库
							for i := range docArr {
								doc := docArr[i].(map[string]interface{})
								doc["rowId"] = primitive.NewObjectID()
								doc["worksheetId"] = wsInfo.Id.Hex()
								doc["createTime"] = time.Now()
								doc["updateTime"] = time.Now()
								doc["isDeleted"] = 0
								doc["tenantId"] = user.TenantId
							}
							if err = w.worksheetRepo.BatchAddFormData(wsInfo.WsCollection, &docArr); err != nil {
								return nil, err
							}
						}
					}
				}
			}
		}
	}

	return &idData, nil
}

// 获取表单列表
func (w *worksheetService) List(mdl *model.DataUserModel) (interface{}, error) {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		filter := bson.M{}
		if wsInfo.WsName != "" {
			filter["wsName"] = bson.M{
				"$regex": fmt.Sprintf(".*%s.*", wsInfo.WsName),
			}
		}
		if mdl.User.RoleName == "AppAdministrator" || mdl.User.RoleName == "Administrator" {
			// 可以获取所有表单
			if wsInfo.VisualId != "" {
				// 若 visualId 不为空，则查询该应用下的所有表单
				filter["visualData"] = wsInfo.VisualId
			}
		} else {
			if len(mdl.User.AppAuths) == 0 {
				// 没有任何应用，即表示不拥有任何表单
				return nil, nil
			}
			if wsInfo.VisualId != "" {
				// 若 visualId 不为空，判断用户是否有这个应用
				hasVisual := false
				for k := range mdl.User.AppAuths {
					if wsInfo.VisualId == k {
						// 用户有这个应用
						hasVisual = true
						break
					}
				}
				if hasVisual {
					filter["visualData"] = wsInfo.VisualId
				} else {
					return nil, nil
				}
			} else {
				// 获取用户拥有的所有应用的表单, 包括自己创建的表单
				ids := bson.A{
					bson.M{
						"owner": mdl.User.GetId(),
					},
				}
				for k := range mdl.User.AppAuths {
					ids = append(ids, bson.M{
						"visualData": k,
					})
				}
				filter = bson.M{
					"$or": ids,
				}
			}
		}
		mdl.Filter = &filter
		result, err := w.worksheetRepo.Find(mdl)
		if err != nil {
			return nil, err
		}
		count, err := w.worksheetRepo.Count(mdl)
		if err != nil {
			return nil, err
		}
		if mdl.Page == nil {
			mdl.Page = &model.Page{
				Current: 0,
				Size:    0,
			}
		}
		res := server.PageResult{
			CgsResult: server.CgsResult{
				Code: 200,
				Msg:  "Get Successfully!",
				Data: result,
			},
			PageNo:     mdl.Page.Current,
			PageSize:   mdl.Page.Size,
			TotalCount: count,
		}
		res.CalculateTotalPage()
		return res, nil
	} else {
		return nil, errors.New("WorksheetInfo type error")
	}
}

// 添加表单
func (w *worksheetService) Save(mdl *model.DataUserModel) error {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		// 需要更新下每个字段的类型
		if wsInfo.Id.IsZero() {
			wsInfo.Id = primitive.NewObjectID()
		}
		wsInfo.WsCollection = "ws" + wsInfo.Id.Hex()
		wsInfo.ResolveDataType()
		err := w.worksheetRepo.Insert(mdl)
		return err
	} else {
		return errors.New("WorksheetInfo type error")
	}
}

// 修改表单信息
func (w *worksheetService) Update(mdl *model.DataUserModel) error {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		// 需要更新下每个字段的类型
		if wsInfo.Id.IsZero() {
			return errors.New("worksheetId is empty")
		}
		wsInfo.ResolveDataType()
		err := w.worksheetRepo.Update(mdl)
		return err
	} else {
		return errors.New("WorksheetInfo type error")
	}
}

// 修改表单信息
func (w *worksheetService) UpdateFields(mdl *model.DataUserModel) error {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		// 需要更新下每个字段的类型
		if wsInfo.Id.IsZero() {
			return errors.New("worksheetId is empty")
		}

		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		fields := []*Field{}
		for _, field := range wsInfoRes.Fields {
			for _, f := range wsInfo.Fields {
				if field.Name == f.Name {
					for key := range f.Options {
						field.Options[key] = f.Options[key]
					}
				}
			}
			fields = append(fields, field)
		}

		wsInfo.Fields = fields
		err = w.worksheetRepo.Update(mdl)
		return err
	} else {
		return errors.New("WorksheetInfo type error")
	}
}

// 逻辑删除表单
func (w *worksheetService) RemoveLogic(mdl *model.DataUserModel) error {
	if wsInfo, ok := mdl.Data.(*WorksheetInfo); ok {
		if wsInfo.Id.IsZero() {
			return errors.New("worksheetId is empty")
		}
		err := w.worksheetRepo.DeleteLogic(mdl)
		return err
	} else {
		return errors.New("WorksheetInfo type error")
	}
}

func (w *worksheetService) AddRow(mdl *model.DataUserModel) error {
	if wsRowData, ok := mdl.Data.(*WsRowData); ok {
		// 1. 查询表单信息
		/*worksheetId, err := primitive.ObjectIDFromHex(wsRowData.WorksheetId)
		if err != nil {
			return err
		}*/
		wsInfo := &WorksheetInfo{
			Id: wsRowData.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 权限校验
		if len(wsInfoRes.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[1]) {
			return errors.New("Permission denied.")
		}
		if len(wsInfoRes.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[2]) {
			return errors.New("Permission denied.")
		}

		// 2. 添加数据
		wsRowData.WsInfo = wsInfoRes

		// 检查记录数
		err = w.checkLicense(wsRowData.WsInfo.WsCollection, 1)
		if err != nil {
			return err
		}

		err = wsRowData.TransferData()
		if err != nil {
			return err
		}
		err = w.worksheetRepo.AddOneFormData(mdl)

		// 向前端推一下数据
		if err == nil {
			rowById, err := w.GetRowById(mdl)
			if err == nil {
				server.WebsocketHub.Send(&server.BroadcastMessage{Type: WsUpdateRow, Data: rowById})
			}
		}

		return err
	} else {
		return errors.New("WsRowData type error")
	}
}

func (w *worksheetService) BatchAddRow(mdl *model.DataUserModel) error {
	if batchAddRowVo, ok := mdl.Data.(*BatchAddRowVo); ok {
		// 1. 查询表单信息
		wsInfo := &WorksheetInfo{
			Id: batchAddRowVo.WorksheetId,
		}
		result, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: wsInfo,
			User: mdl.User,
		})
		if err != nil {
			return err
		}
		if result == nil {
			return errors.New("worksheet is no found")
		}
		wsInfoRes := result.(*WorksheetInfo)

		// 权限校验
		if len(wsInfoRes.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[1]) {
			return errors.New("Permission denied.")
		}
		if len(wsInfoRes.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfoRes.VisualData[2]) {
			return errors.New("Permission denied.")
		}

		// 2. 添加数据
		batchAddRowVo.WsInfo = wsInfoRes

		// 检查记录数
		err = w.checkLicense(batchAddRowVo.WsInfo.WsCollection, len(batchAddRowVo.Rows))
		if err != nil {
			return err
		}

		err = w.worksheetRepo.BatchAddRow(mdl)
		return err
	} else {
		return errors.New("WsRowDataVo type error")
	}
}

func (w *worksheetService) checkLicense(collectionName string, adds int) error {

	return nil
}

func (w *worksheetService) GetOne(mdl *model.DataUserModel) (interface{}, error) {
	if _, ok := mdl.Data.(*WorksheetInfo); ok {
		mdl.FindOneOptions = &options.FindOneOptions{
			Projection: bson.M{
				"wsCollection": 0,
				"tenantId":     0,
			},
		}
		// 验证权限
		result, err := w.worksheetRepo.FindOne(mdl)
		if err != nil {
			return nil, err
		}
		if result == nil {
			return nil, model.NotFoundError("worksheet")
		}
		return result, nil
		//if wi, ok := result.(*WorksheetInfo); ok {
		//	if len(wi.VisualData) != 2 || mdl.User.HasVisualAuth(wi.VisualData[1]) {
		//		return result, nil
		//	} else {
		//		return nil, errors.New("Permission denied.")
		//	}
		//} else {
		//	return nil, model.NotFoundError("worksheet")
		//}
	} else {
		return nil, model.NewTypeError("worksheetInfo")
	}
}

func (w *worksheetService) GetFilterRows(mdl *model.DataUserModel) (interface{}, error) {
	if filterParam, ok := mdl.Data.(*FilterParam); ok {
		// 查询表单信息
		wsRes, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: &WorksheetInfo{
				Id: filterParam.WorksheetId,
			},
		})
		if err != nil {
			return nil, err
		}
		if wsRes == nil {
			return nil, model.NotFoundError("worksheet id " + filterParam.WorksheetId.Hex())
		}
		wsInfo := wsRes.(*WorksheetInfo)

		// 权限校验
		if len(wsInfo.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfo.VisualData[1]) {
			return nil, errors.New("Permission denied.")
		}
		if len(wsInfo.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfo.VisualData[2]) {
			return nil, errors.New("Permission denied.")
		}

		filterParam.WsCollection = wsInfo.WsCollection

		projection := bson.M{
			"_id":       0,
			"isDeleted": 0,
		}
		mdl.Page = &model.Page{
			Current: filterParam.PageNo,
			Size:    filterParam.PageSize,
		}
		mdl.ResolvePageOption()
		mdl.Options.SetProjection(projection)
		mdl.Options.SetSort(bson.M{"updateTime": -1})
		// 排序
		sortField := filterParam.SortField
		isAsc := -1
		if filterParam.IsAsc {
			isAsc = 1
		}
		if sortField != "" {
			mdl.Options.Sort = bson.M{
				sortField: isAsc,
			}
		}
		filter := filterParam.GetFilterParam(wsInfo).Map()
		mdl.Filter = &filter

		data, err := w.worksheetRepo.FindFilterFormData(mdl)
		if err != nil {
			return nil, err
		}
		doc := data.(bson.A)
		docs := FormatDataType(doc, *wsInfo)

		filter["isDeleted"] = 0
		count, _ := w.worksheetRepo.CountRows(filterParam.WsCollection, &filter)

		result := server.PageResult{
			CgsResult: server.CgsResult{
				Code:    200,
				Msg:     "Get Successfully!",
				Data:    docs,
				Success: true,
			},
			PageNo:     mdl.Page.Current,
			PageSize:   mdl.Page.Size,
			TotalCount: count,
		}
		result.CalculateTotalPage()
		return result, nil
	} else {
		return nil, model.NewTypeError("filterParam")
	}
}

func (w *worksheetService) GetRowById(mdl *model.DataUserModel) (interface{}, error) {
	if wsRowData, ok := mdl.Data.(*WsRowData); ok {
		// 查询表单信息
		wsRes, err := w.worksheetRepo.FindOne(&model.DataUserModel{
			Data: &WorksheetInfo{
				Id: wsRowData.WorksheetId,
			},
		})
		if err != nil {
			return nil, err
		}
		if wsRes == nil {
			return nil, model.NotFoundError("worksheet id " + wsRowData.WorksheetId.Hex())
		}
		wsInfo := wsRes.(*WorksheetInfo)
		wsRowData.WsInfo = wsInfo

		// 权限校验
		if len(wsInfo.VisualData) == 2 && !mdl.User.HasVisualAuth(wsInfo.VisualData[1]) {
			return nil, errors.New("Permission denied.")
		}
		if len(wsInfo.VisualData) == 3 && !mdl.User.HasVisualAuth(wsInfo.VisualData[2]) {
			return nil, errors.New("Permission denied.")
		}

		mdl.FindOneOptions = &options.FindOneOptions{
			Projection: bson.M{
				"_id":       0,
				"isDeleted": 0,
			},
		}

		return w.worksheetRepo.GetRowById(mdl)
	} else {
		return nil, model.NewTypeError("wsRowData")
	}
}
